package csharp.cauth.commands;

import java.util.logging.Level;

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.PlayerInventory;

import com.nijiko.permissions.PermissionHandler;

import csharp.cauth.CAuth;
import csharp.cauth.Language;
import csharp.cauth.PlayersSL;
import csharp.cauth.PluginConfig;
import csharp.cauth.properties.InventoryProp;
import csharp.cauth.properties.PlayerProp;
import csharp.cauth.utils.Log;
import csharp.cauth.utils.MD5;

/**
 * @author Ярослав (CSharp) "/login" command. Using for login player into world.
 */
public class CALogin implements CommandExecutor
{
	private static CAuth plugin;

	public CALogin(CAuth cAuth)
	{
		CALogin.plugin = cAuth;
	}

	@Override
	public boolean onCommand(CommandSender sender, Command command,
			String label, String[] split)
	{
		if (sender instanceof Player)
		{
			Player player = (Player) sender;

			if (PluginConfig.usePermissions)
				return permissionsExecutor(player, split);
			else
				return executor(player, split);
		}

		return true;
	}

	private boolean executor(Player player, String[] split)
	{
		if (split.length > 0)
		{
			for (PlayerProp playerProp : CAuth.players)
			{
				if (playerProp.getLogin().equalsIgnoreCase(player.getName())
						&& playerProp.getPassword().equalsIgnoreCase(
								MD5.getHash(split[0])))
				{
					PlayerInventory inventory = player.getInventory();
					InventoryProp inventoryProp = CAuth.unauthorized
							.get(player);

					if (inventoryProp != null)
					{
						inventory.setContents(inventoryProp.getItems());

						inventory.setBoots(inventoryProp.getBoots());
						inventory.setChestplate(inventoryProp.getChest());
						inventory.setLeggings(inventoryProp.getLeggings());
						inventory.setHelmet(inventoryProp.getHelmet());

						CAuth.authorized.add(player);
						CAuth.unauthorized.remove(player);

						player.sendMessage("[CAuth] " + Language.WELCOME);
						player.teleport(playerProp.getLastLoc());

						if (PluginConfig.useMySQL)
							PlayersSL.updateLastLogin(playerProp.getId());

						return true;
					}
					else
					{
						player.sendMessage("[CAuth] "
								+ Language.ERROR_HAS_OCCURED);

						return true;
					}
				}
			}

			if (CAuth.wrongEnters.containsKey(player))
			{
				CAuth.wrongEnters
						.put(player, CAuth.wrongEnters.get(player) + 1);
			}
			else
			{
				CAuth.wrongEnters.put(player, 1);
			}

			if (CAuth.wrongEnters.containsKey(player))
			{
				if (CAuth.wrongEnters.get(player) >= PluginConfig.wrongPasswordEnterCount)
				{
					// player.sendMessage("[CAuth] You banned for password brute.");
					player.kickPlayer("[CAuth] "
							+ Language.YOU_BANNED_FOR_PASSWORD_BRUTE);

					ConsoleCommandSender sender = new ConsoleCommandSender(
							plugin.getServer())
					{
						@Override
						public void sendMessage(String message)
						{
							// Nothing.
						}
					};

					plugin.getServer().dispatchCommand(sender,
							"ban " + player.getName());
				}
			}

			// player.sendMessage("[CAuth] Wrong password!");
			player.kickPlayer("[CAuth] " + Language.WRONG_PASSWORD);

			Log.log(Level.INFO, "Player " + player.getDisplayName()
					+ " with IP "
					+ player.getAddress().getAddress().getHostAddress()
					+ " tried to brute password. Kicked.");

			return true;
		}
		else
		{
			player.sendMessage("[CAuth] " + Language.ENTER_PASSWORD);
		}

		return false;
	}

	private boolean permissionsExecutor(Player player, String[] split)
	{
		PermissionHandler permissionHandler = CAuth.permissionHandler;

		if (permissionHandler == null)
		{
			Log.log(Level.INFO,
					"No permissions plugin installed, default command executor selected.");

			PluginConfig.usePermissions = false;

			return executor(player, split);
		}

		if (permissionHandler.has(player, "CAuth.login"))
		{
			if (split.length > 0)
			{
				for (PlayerProp playerProp : CAuth.players)
				{
					if (playerProp.getLogin()
							.equalsIgnoreCase(player.getName())
							&& playerProp.getPassword().equalsIgnoreCase(
									MD5.getHash(split[0])))
					{
						PlayerInventory inventory = player.getInventory();
						InventoryProp inventoryProp = CAuth.unauthorized
								.get(player);

						if (inventoryProp != null)
						{
							inventory.setContents(inventoryProp.getItems());

							inventory.setBoots(inventoryProp.getBoots());
							inventory.setChestplate(inventoryProp.getChest());
							inventory.setLeggings(inventoryProp.getLeggings());
							inventory.setHelmet(inventoryProp.getHelmet());

							CAuth.authorized.add(player);
							CAuth.unauthorized.remove(player);

							player.sendMessage("[CAuth] " + Language.WELCOME);
							player.teleport(playerProp.getLastLoc());

							if (PluginConfig.useMySQL)
								PlayersSL.updateLastLogin(playerProp.getId());

							return true;
						}
						else
						{
							player.sendMessage("[CAuth] "
									+ Language.ERROR_HAS_OCCURED);

							return true;
						}
					}
				}

				if (CAuth.wrongEnters.containsKey(player))
				{
					CAuth.wrongEnters.put(player,
							CAuth.wrongEnters.get(player) + 1);
				}
				else
				{
					CAuth.wrongEnters.put(player, 1);
				}

				if (CAuth.wrongEnters.containsKey(player))
				{
					if (CAuth.wrongEnters.get(player) >= PluginConfig.wrongPasswordEnterCount)
					{
						// player.sendMessage("[CAuth] You banned for password brute.");
						player.kickPlayer("[CAuth] "
								+ Language.YOU_BANNED_FOR_PASSWORD_BRUTE);

						ConsoleCommandSender sender = new ConsoleCommandSender(
								plugin.getServer())
						{
							@Override
							public void sendMessage(String message)
							{
								// Nothing.
							}
						};

						plugin.getServer().dispatchCommand(
								sender,
								"ban-ip "
										+ player.getAddress().getAddress()
												.getHostAddress());
					}
				}

				// player.sendMessage("[CAuth] Wrong password!");
				player.kickPlayer("[CAuth] " + Language.WRONG_PASSWORD);

				Log.log(Level.INFO, "Player " + player.getDisplayName()
						+ " with IP "
						+ player.getAddress().getAddress().getHostAddress()
						+ " tried to brute password. Kicked.");

				return true;
			}
			else
			{
				player.sendMessage("[CAuth] " + Language.ENTER_PASSWORD);
			}
		}

		return false;
	}
}
